
function Promise(executor) {
    this.PromiseState = 'pending';
    this.PromiseResult = undefined;
    this.callbacks = [];
    let self = this;
    function resolve(value) {
        if (self.PromiseState !== 'pending') return;
        self.PromiseState = 'fulfilled';
        self.PromiseResult = value;
        setTimeout(()=>{
            self.callbacks.forEach(item => {
                item.onResolved();
            })
        })
    }
    function reject(reason) {
        if (self.PromiseState !== 'pending') return;
        self.PromiseState = 'rejected';
        self.PromiseResult = reason;
        setTimeout(()=>{
            self.callbacks.forEach(item => {
                item.onRejected();
            })
        })
    }
    try {
        executor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}

Promise.prototype.then = function (onResolved, onRejected) {
    return new Promise((resolve, reject) => {
        if(typeof onRejected !== 'function'){
            onRejected = reason =>{
                throw reason;
            }
        }
        if(typeof onResolved !== 'function'){
            onResolved = v => v;
        }
        let changeState = (type)=>{
            try{
                let rs = type(this.PromiseResult);
                if (rs instanceof Promise) {
                    rs.then(resolve, reject);
                } else {
                    resolve(rs);
                }
            }catch(e){
                reject(e);
            }
        }
        if (this.PromiseState === 'fulfilled') {
            setTimeout(()=>{
                changeState(onResolved);
            })
        }
        if (this.PromiseState === 'rejected') {
            setTimeout(()=>{
                changeState(onRejected);
            })
        }
        if (this.PromiseState === 'pending') {
            this.callbacks.push({
                onRejected: () => {
                    changeState(onRejected);
                },
                onResolved: () => {
                    changeState(onResolved);
                }
            })
        }
    })
}

Promise.prototype.catch = function(onRejected){
    return this.then(undefined, onRejected);
}

Promise.resolve = function(value){
    return new Promise((resolve,reject)=>{
        if(value instanceof Promise){
            value.then(resolve,reject);
        }else{
            resolve(value);
        }
    })
}


Promise.all = function(promiseArr){
    let resultArr = [];
    return new Promise((resolve, reject)=>{
        for(let i = 0; i < promiseArr.length; i++){
            promiseArr[i].then(value=>{
                resultArr[i] = value;
                if(resultArr.length === promiseArr.length){
                    resolve(resultArr);
                }
            },reason=>{
                resolve(reason);
            })
        }
    })
}